module.exports = app => {
    // 要想使用express，该文件就需要引入express
    const express = require('express')
     // 定义路由方法，将我们定义的路由挂载到express
     const router = express.Router({
        mergeParams: true //合并参数
    })
    // 由于express不能获取到文件上传的数据，所以我们要使用获取文件数据的类包multer，定义在中间件中使用
    const multer = require('multer')
    const assert = require('http-assert') //http-assert(用于测试函数、值是否存在、是否正确的工具包)
    const jwt = require('jsonwebtoken')
    const AdminUser = require('../../models/AdminUser')
   
    
    // router挂载post方法，因为表单传值时用的就是post传值
    // 接口地址是categories，接收的是分类功能（创建分类、修改分类、查询分类列表）的操作
    // 之后其他功能实现与此模板相同，与此功能平级

    // 上传数据（增）
    router.post('/', async (req, res) => {
        const model = await req.Model.create(req.body)
        res.send(model)
    })
    // 查询数据（查）
    router.get('/', async (req, res) => {
        const queryOptions = {}
        if (req.Model.modelName === 'Category') {
            queryOptions.populate = 'parent'
        } // 保证通用性和扩展性
        const items = await req.Model.find().setOptions(queryOptions).limit(100)
        res.send(items)
    })
    // 根据id查询数据（查）
    router.get('/:id', async (req, res) => {
        const model = await req.Model.findById(req.params.id)
        res.send(model)
    })
    // 编辑数据（改）
    router.put('/:id', async (req, res) => {
        const model = await req.Model.findByIdAndUpdate(req.params.id, req.body)
        res.send(model)
    })
    // 删除数据（删）
    router.delete('/:id', async (req, res) => {
        await req.Model.findByIdAndDelete(req.params.id, req.body)
        res.send({
            success: true
        })
    })
  // 登录校验中间件
//   const authMiddleware = require('../../middleware/auth')
const authMiddleware = require('../../middleware/auth')
  const resourceMiddleware = require('../../middleware/resource')
    app.use('/admin/api/rest/:resource',authMiddleware(), resourceMiddleware(),router)

    // dest目标地址,__dirname表示当前文件,要以当前文件为准找到我们想要把图片保存到的文件夹
    const upload = multer({ dest: __dirname + ('/../../uploads') })
    // file是前台传入调用图片上传接口upload时formdata里边的数据名
    // upload.single('img')表示解析单个文件夹，且key值为'file'
    app.post('/admin/api/upload',authMiddleware(), upload.single('file'), async (req, res) => {
        // multer在解析完请求体后，会想Request对象中添加一个body对象（包含所提交表单的文本字段，如果有）和一个file（包含通过表单上传的文件）或files（对文件上传时使用files对象）对象
        const file = req.file
        // 定义图片的路由地址，将路由地址放入准备输出的file中，从而方便前台调用查询
        file.url = `http://localhost:3000/uploads/${file.filename}`
        res.send(file)
        // 其中filename就是我们保存下来文件的文件名，所以我们要访问到图片的话，就要通过接口地址再加上这个filename，也就是给图片添加路由地址
        // 在node.js中与其他后端不同，这里的文件地址都是由我们自己定义的，而不是真实路由
    })

    // 登录接口
    app.post('/admin/api/login', async (req, res) => {
        const { username, password } = req.body
        // 1.根据用户名找用户
        // 利用模型查找指定用户,同时将密码连带查询出来
        const user = await AdminUser.findOne({ username: username }).select('+password')
        // if (!user) {
        //     return res.status(422).send({
        //         message: "用户不存在"
        //     })
        // }
        assert(user, 422, '用户不存在')
        // 2.校验密码
        const isValid = require('bcrypt').compareSync(password, user.password)
        // if(!isValid) {
        //     return res.status(422).send({
        //         message: '密码错误'
        //     })
        // }
        assert(isValid, 422, '密码错误')
        // 3.返回token
        //生成token的方法是定义一个密钥secret，使用sign方法根据密钥将用户的id包含进去
        // 注意：密钥需要全局定义，因为解析token同时需要密钥
        // app.get()中单个参数就是获取全局配置，多个值就是定义路由
        const token = jwt.sign({ id: user._id }, app.get('secret'))
        res.send({ token })
    })

    // 错误处理函数 中间件
    // 报错422没问题，但是message没有接收到。是因为http-assert是以抛出异常的方式进行报错的，前端无法获取到json数据。
    // 所以要写一个错误处理函数，对抛出的异常做处理，将异常中的内容进行捕获并传给前端admin
    app.use(async (err, req, res, next) => {
        // 如果发送错误码，将错误码放到res输出到前端显示
        // 如果获取不到状态码，就是500错误，所以状态码报错或500报错
        res.status(err.statusCode || 500).send({
            message: err.message
        })
    })
}